package com.hra.camera2demo;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.util.Log;
import android.util.Range;
import android.util.Size;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Camera2ConfigManager {
    private static final String TAG = "CameraConfigManagerDebug";

    public static final String KEY_SCENE_MODE = "scene_mode";
    public static final String KEY_FOCUS_MODE = "focus_mode";
    public static final String KEY_WHITE_BALANCE = "white_balance";
    public static final String KEY_ISO_VALUE = "iso_value";
    public static final String KEY_EXPOSURE_TIME = "exposure_time";
    public static final String KEY_PREVIEW_SIZE = "preview_size";
    public static final String KEY_CAPTURE_SIZE = "capture_size";
    public static final String KEY_VIDEO_SIZE = "video_size";

    // sceneMode
    public int sceneModeIndex = 0;
    public int[] supportedSceneModes;
    public int sceneMode = CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED;

    // focusMode（AF）
    public int focusModeIndex = 0;
    public int[] supportedFocusModes;
    public int focusMode = CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_PICTURE;

    // whiteBalance
    public int whiteBalanceModeIndex = 0;
    public int[] supportedWhiteBalanceModes;
    public int whiteBalanceMode = CameraCharacteristics.CONTROL_AWB_MODE_AUTO;

    // isoValue
    public int isoModeIndex;
    public int[] supportedISOModes;
    public int isoValue = 0;

    // exposureTime
    public int exposureTimeIndex;
    public long[] supportedExposureTimes;
    public long exposureTime = 0L;

    // previewSize
    public int previewSizeIndex = 0;
    public List<Size> supportedPreviewSizes;
    public Size previewSize;

    // captureSize
    public int captureSizeIndex = 0;
    public List<Size> supportedCaptureSizes;
    public Size captureSize;

    // videoSize
    public int videoSizeIndex = 0;
    public List<Size> supportedVideoSizes;
    public final List<CamcorderProfile> supportedCamcorderProfiles = new ArrayList<>();
    public Size videoSize;
    public CamcorderProfile profile;

    private final SharedPreferences mPreferences;
    private final Context mContext;
    private CameraCharacteristics mCameraCharacteristics;
    private String mCameraID = "0";


    public Camera2ConfigManager(Context context, SharedPreferences preferences) {
        mContext = context;
        mPreferences = preferences;
    }

    // 初始化配置（从CameraCharacteristics读取）
    public void initConfigs(CameraCharacteristics characteristics, String cameraId) {
        if (characteristics == null || cameraId == null) return;
        mCameraCharacteristics = characteristics;
        mCameraID = cameraId;

        initSceneModes();
        initFocusMode();
        initWhiteBalanceMode();
        initISOModes();
        initExposureTimes();
        initPreviewSize();
        initCaptureSize();
        initVideoSizeProfile();

        Log.d(TAG, "openCamera: supportedSceneModes" + Arrays.toString(supportedSceneModes));
        Log.d(TAG, "openCamera: supportedFocusModes" + Arrays.toString(supportedFocusModes));
        Log.d(TAG, "openCamera: supportedWhiteBalanceModes" + Arrays.toString(supportedWhiteBalanceModes));
        Log.d(TAG, "openCamera: supportedISOModes" + Arrays.toString(supportedISOModes));
        Log.d(TAG, "openCamera: supportedExposureTimes" + Arrays.toString(supportedExposureTimes));
        Log.d(TAG, "openCamera: supportedPreviewSizes" + supportedPreviewSizes);
        Log.d(TAG, "openCamera: supportedCaptureSizes" + supportedCaptureSizes);
        Log.d(TAG, "openCamera: supportedVideoSizes" + supportedVideoSizes);
    }


    private void initSceneModes() {
        sceneMode = mPreferences.getInt(KEY_SCENE_MODE, sceneMode);
        // 获取支持的取景模式列表
        if (mCameraCharacteristics == null) return;
        supportedSceneModes = mCameraCharacteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES);
        supportedSceneModes = Camera2ConfigHelper.addIfNotPresent(supportedSceneModes, CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED);
        sceneModeIndex = Camera2ConfigHelper.getIndex(supportedSceneModes, sceneMode);
        sceneMode = supportedSceneModes[sceneModeIndex];
    }

    private void initFocusMode() {
        focusMode = mPreferences.getInt(KEY_FOCUS_MODE, focusMode);
        // 获取支持的AF（对焦）模式列表
        if (mCameraCharacteristics == null) return;
        supportedFocusModes = mCameraCharacteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
        focusModeIndex = Camera2ConfigHelper.getIndex(supportedFocusModes, focusMode);
        focusMode = supportedFocusModes[focusModeIndex];
    }

    private void initWhiteBalanceMode() {
        whiteBalanceMode = mPreferences.getInt(KEY_WHITE_BALANCE, whiteBalanceMode);
        // 获取支持的白平衡模式列表
        if (mCameraCharacteristics == null) return;
        supportedWhiteBalanceModes = mCameraCharacteristics.get(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES);
        whiteBalanceModeIndex = Camera2ConfigHelper.getIndex(supportedWhiteBalanceModes, whiteBalanceMode);
        whiteBalanceMode = supportedWhiteBalanceModes[whiteBalanceModeIndex];
    }

    public void initISOModes() {
        isoValue = mPreferences.getInt(KEY_ISO_VALUE, 0);
        // 获取ISO物理范围
        if (mCameraCharacteristics == null) return;
        Range<Integer> isoRange = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
        // 生成ISO选项列表
        List<Integer> isoList = new ArrayList<>();
        // 添加自动选项
        isoList.add(0);
        if (isoRange != null) {
            int minValue = isoRange.getLower();
            int maxValue = isoRange.getUpper();
            minValue = minValue % 100 == 0 ? minValue : (minValue / 100 + 1) * 100;
            for (int i = minValue; i <= maxValue; i = i * 2) {
                isoList.add(i);
            }
        }
        // 将isoList转化为数组
        supportedISOModes = isoList.stream().mapToInt(i -> i).toArray();
        isoModeIndex = Camera2ConfigHelper.getIndex(supportedISOModes, isoValue);
        isoValue = supportedISOModes[isoModeIndex];
    }

    public void initExposureTimes() {
        exposureTime = mPreferences.getLong(KEY_EXPOSURE_TIME, 0);
        // 获取ISO物理范围
        if (mCameraCharacteristics == null) return;
        Range<Long> exposureTimeRange = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
        Log.w(TAG, "initExposureTimes: exposureTimeRange=" + exposureTimeRange);
        List<Long> exposureList = new ArrayList<>();
        // 添加自动选项
        exposureList.add(0L);
        if (exposureTimeRange != null) {
            long minExposure = exposureTimeRange.getLower();
            long maxExposure = exposureTimeRange.getUpper();
            for (long i = maxExposure; i >= minExposure; i /= 2) {
                exposureList.add(i);
            }
        }
        // 将List转化为数组
        supportedExposureTimes = exposureList.stream().mapToLong(i -> i).toArray();
        exposureTimeIndex = Camera2ConfigHelper.getIndex(supportedExposureTimes, exposureTime);
        exposureTime = supportedExposureTimes[exposureTimeIndex];
    }

    private void initPreviewSize() {
        try {
            previewSize = Size.parseSize(mPreferences.getString(KEY_PREVIEW_SIZE, ""));
        } catch (NumberFormatException ignored) {
        }
        // 获取支持的预览尺寸列表
        if (mCameraCharacteristics == null) return;
        StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        supportedPreviewSizes = Arrays.asList(map.getOutputSizes(SurfaceTexture.class));
        supportedPreviewSizes.sort(new Camera2ConfigHelper.CompareSizesByArea());
        previewSizeIndex = Camera2ConfigHelper.getIndex(supportedPreviewSizes, previewSize);
        previewSize = supportedPreviewSizes.get(previewSizeIndex);
    }

    private void initCaptureSize() {
        try {
            captureSize = Size.parseSize(mPreferences.getString(KEY_CAPTURE_SIZE, ""));
        } catch (NumberFormatException ignored) {
        }
        // 获取支持的拍照尺寸列表
        if (mCameraCharacteristics == null) return;
        StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        supportedCaptureSizes = Camera2ConfigHelper.getSupportedPictureSize(map, ImageFormat.JPEG);
        supportedCaptureSizes.sort(new Camera2ConfigHelper.CompareSizesByArea());
        captureSizeIndex = Camera2ConfigHelper.getIndex(supportedCaptureSizes, captureSize);
        captureSize = supportedCaptureSizes.get(captureSizeIndex);
    }

    private void initVideoSizeProfile() {
        try {
            videoSize = Size.parseSize(mPreferences.getString(KEY_VIDEO_SIZE, ""));
        } catch (NumberFormatException ignored) {
        }
        // 获取支持的视频尺寸列表
        if (mCameraCharacteristics == null) return;
        StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        supportedVideoSizes = new ArrayList<>(Arrays.asList(map.getOutputSizes(MediaRecorder.class)));
        supportedVideoSizes.sort(new Camera2ConfigHelper.CompareSizesByArea());
        listSupportedCamcorderProfiles();
        videoSizeIndex = Camera2ConfigHelper.getIndex(supportedVideoSizes, videoSize);
        videoSize = supportedVideoSizes.get(videoSizeIndex);
        for (CamcorderProfile profile : supportedCamcorderProfiles) {
            if (profile.videoFrameWidth == videoSize.getWidth() && profile.videoFrameHeight == videoSize.getHeight()) {
                this.profile = profile;
                break;
            }
        }
    }


    @SuppressLint("InlinedApi")
    private void listSupportedCamcorderProfiles() {
        if (supportedVideoSizes == null) return;
        try {
            List<Integer> qualities = new ArrayList<>();
            for (int i = CamcorderProfile.QUALITY_8KUHD; i >= CamcorderProfile.QUALITY_LOW; i--) {
                qualities.add(i);
            }
            supportedCamcorderProfiles.clear();
            int cameraId = Integer.parseInt(mCameraID);
            for (int quality : qualities) {
                if (CamcorderProfile.hasProfile(cameraId, quality)) {
                    CamcorderProfile profile = CamcorderProfile.get(cameraId, quality);
                    Size size = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
                    if (supportedVideoSizes.contains(size)) {
                        supportedCamcorderProfiles.add(profile);
                    }
                }
            }
            // 收集所有 CamcorderProfile 的分辨率到集合
            Set<Size> profileSizes = new HashSet<>();
            for (CamcorderProfile profile : supportedCamcorderProfiles) {
                Size size = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
                profileSizes.add(size);
            }
            // 过滤 supportedVideoSizes，保留匹配项，删除不在 CamcorderProfile 中的分辨率
            supportedVideoSizes.removeIf(size -> !profileSizes.contains(size));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    // 显示配置选择对话框
    public void showConfigDialog(String title, String[] items, int currentIndex, Config2ChangeListener listener) {
        new AlertDialog.Builder(mContext)
                .setTitle(title)
                .setSingleChoiceItems(items, currentIndex, (dialog, which) -> {
                    if (listener != null) {
                        listener.onConfigSelected(which);
                    }
                    dialog.dismiss();
                })
                .show();
    }

    // 配置变更监听接口
    public interface Config2ChangeListener {
        void onConfigSelected(int index);
    }
}
